package Tracer;

import java.util.Vector;

import XMLScene.RTIObject;

/**
 * ClassName : RTRay RTRay is a class represents one ray. A ray is defined by
 * start point and direction which are both RTVectors. RTRay is used to detect
 * the hit to objects(sphere,plane,triangle). If the ray hit some objects it
 * will return a list which have all objects hit by the ray.
 * 
 * @version 1.0 Oct 5th 2009
 * @author LU LIU & PENG ZHANG
 */
public class RTRay {

	/**
	 * The direction of the ray
	 */
	private RTVector direction;
	/**
	 * The start point of the ray
	 */
	private RTVector startPoint;

	/**
	 * Constructor of RTRay, default constructor
	 */
	public RTRay() {
		startPoint = new RTVector(0, 0, 0);
		direction = new RTVector(0, 0, 0);
	}

	/**
	 * Another constructor of RTRay
	 * 
	 * @param start
	 *            the start point of the ray
	 * @param end
	 *            the end point of the ray
	 */
	public RTRay(RTVector start, RTVector end) {
		startPoint = new RTVector(start);
		direction = RTVector.normaliseVectors(RTVector.sumVectors(end, RTVector
				.reverseVector(startPoint)));
	}

	/**
	 * objectHitDetect This method is used to calculate the hit point of ray and
	 * object. Object can be sphere, plane and triangle. If the ray hit on the
	 * object, it'll return a RTHitpointObjMap which contains the details of the
	 * hit point.
	 * 
	 * @param obj
	 *            the object which is going to(or not) hit by the ray.
	 * @param hitPointObjSingleMap
	 *            the return value which contains the details of the hitpoint
	 */
	private RTHitpointObjMap objectHitDetect(RTIObject obj,
			RTHitpointObjMap hitPointObjSingleMap) {
		return obj.objectHitDetect(this, hitPointObjSingleMap);

	}

	/**
	 * objectListHitDetect This method is used to calculate the hit point of ray
	 * and a list of objects. The vector list contains Objects such as spheres,
	 * planes and triangles. It will call objectHitDetect to see if the ray is
	 * hit on one object.If the ray hit on the object, it'll return a
	 * RTHitpointObjMap which contains the details of the hitpoint. The function
	 * will return a Vector list of RTHitpointObjMap.
	 * 
	 * @param objList
	 *            the vector list of objects
	 * @param hitPointObjMapList
	 *            the return value which is a vector list of RTHitpointObjMap
	 */
	public Vector<RTHitpointObjMap> objectListHitDetect(
			Vector<RTIObject> objList,
			Vector<RTHitpointObjMap> hitPointObjMapList) {
		RTHitpointObjMap hitPointObjSingleMap = new RTHitpointObjMap();
		hitPointObjMapList.removeAllElements();
		for (int i = 0; i < objList.size(); i++) {
			RTIObject currentObj = objList.get(i);
			hitPointObjSingleMap = objectHitDetect(currentObj,
					hitPointObjSingleMap);
			if (hitPointObjSingleMap != null) {
				// add all hit point and its object
				hitPointObjMapList.addElement(hitPointObjSingleMap);
			}
			hitPointObjSingleMap = new RTHitpointObjMap();
		}
		hitPointObjSingleMap = null;
		return hitPointObjMapList;
	}

	public RTVector getStartPoint() {
		return startPoint;
	}

	/**
	 * @param startPoint
	 *            the start point of ray
	 */
	public final void setRay(final RTVector startPt, final RTVector endPoint) {
		if (startPt != null && endPoint != null) {
			startPoint = startPt;
			direction = RTVector.normaliseVectors(RTVector.sumVectors(endPoint,
					RTVector.reverseVector(startPoint)));
		} else {
			System.out.printf("Null Pointer!");
		}
	}

	/**
	 * Getter of ray direction
	 * 
	 * @return the direction vector
	 */
	public RTVector getDirection() {
		return direction;
	}
}